package roles_service

import (
	"encoding/json"
	"fmt"
	"peilian-api/app/global/databases/tables"
	"peilian-api/app/global/errors"
	"peilian-api/app/global/variable"
	"peilian-api/app/model"
	"strings"

	"github.com/gin-gonic/gin"
)

var (
	RoleNameMap = map[string]string{
		"all":        "", //all 字段为角色权限管理服务
		"school":     "学校管理员",
		"academy":    "学院管理员",
		"profession": "专业管理员",
	}
	RoleLevelMap = map[string]int{
		"all":        1, //all 字段为角色权限管理服务
		"school":     2,
		"academy":    3,
		"profession": 4,
	}
)

type RolesService struct{}

func (rs *RolesService) AddRoles(ctx *gin.Context, rsr model.RolesAddRes) *errors.ErrRes {
	// 1. 获取该用户的id
	var us = tables.User{}
	uid, exists := ctx.Get("uid")
	if !exists {
		return errors.NewErrInfo(10001, fmt.Errorf("您无权操作"))
	}
	// 根据uid获取user信息
	us, _ = tables.GetAgentInfoByUid(uid.(uint))
	// mapstructure.Decode(u, &us)
	us.ID = uid.(uint)
	belongId := us.ConstituteID
	var roleObj = tables.Roles{}

	// 查询该角色是否存在
	r, err := roleObj.GetRolesByWhere(map[string]interface{}{"role_name": rsr.RoleName, "belong_to_id": belongId}, "")
	if err != nil || (len(r) != 0 && r[0].ID != 0) {
		return errors.NewErrInfo(10002, fmt.Errorf("该角色名已经存在~"))
	}
	bytePowers, _ := json.Marshal(rsr.Powers)
	roleObj.UserId = uid.(uint)
	roleObj.Level = 0
	roleObj.RoleName = rsr.RoleName
	roleObj.Describe = rsr.Describe
	roleObj.Powers = string(bytePowers)
	roleObj.BelongToId = uint(belongId)
	roleObj.IsCustom = true
	if err := new(tables.Roles).SaveRoles(roleObj); err != nil {
		return errors.NewErrInfo(10003, fmt.Errorf("数据库操作异常"))
	}
	return nil
}

func (rs *RolesService) GetRolesList(ctx *gin.Context, rgr model.RolesListRes) ([]model.RolesListResp, *errors.ErrRes) {
	var out []model.RolesListResp
	var us = tables.User{}
	uid, exists := ctx.Get("uid")
	if !exists {
		return out, errors.NewErrInfo(10001, fmt.Errorf("您无权操作"))
	}

	us, _ = tables.GetAgentInfoByUid(uid.(uint))
	// 拿到用户所属的角色
	r, err := new(tables.Roles).GetRolesByWhere(map[string]interface{}{}, fmt.Sprintf("id = %d", us.RoleId))
	if err != nil && len(r) == 0 {
		return out, nil
	}
	var whereStr = ""
	typ := rgr.Type
	if typ != "all" {
		whereStr = whereStr + fmt.Sprintf("id != 1 and (user_id = 0 and level >= %d)", us.Level)
	} else {
		whereStr = whereStr + fmt.Sprintf("id != 1 and (user_id = 0 and level >= %d) or user_id = %d", us.Level, uid.(uint))
	}

	query := rgr.Query
	//level := RoleLevelMap[typ] //level一定有，因为typ只能是"all｜school｜academy｜profession"中的一个
	if query != "" {
		whereStr = whereStr + ") and (role_name like '%" + query + "%'"
	}

	if typ != "all" {
		if _, ok := RoleNameMap[typ]; ok {
			whereStr = whereStr + fmt.Sprintf(") and (role_name = \"%s\" ) or (user_id = %d", RoleNameMap[typ], uid.(uint))
		}
	}

	rolesArr, _ := new(tables.Roles).GetRolesByWhere(map[string]interface{}{}, whereStr)
	for _, v := range rolesArr {
		out = append(out, model.RolesListResp{Id: v.ID, RoleName: v.RoleName, Describe: v.Describe, IsCustom: v.IsCustom})
	}
	return out, nil
}

func (rs *RolesService) GetRolesById(ctx *gin.Context, rsr model.RolesId) (model.RolesListResp, *errors.ErrRes) {
	var trs model.RolesListResp
	rolesArr, _ := new(tables.Roles).GetRolesByWhere(map[string]interface{}{"id": rsr.Id}, "")
	if len(rolesArr) == 0 {
		return trs, errors.NewErrInfo(10002, fmt.Errorf("您所查询的数据不存在~"))
	}
	if rolesArr[0].ID == 0 {
		return trs, errors.NewErrInfo(10003, fmt.Errorf("您所查询的数据不存在~"))
	}
	trs.Id = rolesArr[0].ID
	trs.Describe = rolesArr[0].Describe
	trs.RoleName = rolesArr[0].RoleName
	str := rolesArr[0].Powers
	var powers []uint
	json.Unmarshal([]byte(str), &powers)
	trs.Powers = powers
	return trs, nil
}

func (rs *RolesService) UpdateRolesById(ctx *gin.Context, rsr model.RolesUpdateRes) *errors.ErrRes {
	// 1. 获取该用户的id
	uid, exists := ctx.Get("uid")
	if !exists {
		return errors.NewErrInfo(10001, fmt.Errorf("您无权操作"))
	}
	// us, _ := tables.GetAgentInfoByUid(uid.(uint))
	var roleId uint
	variable.DB.MySQL.Model(&tables.User{}).Select("RoleId").Where("id=?", uid).Scan(&roleId)
	var isCustom bool
	variable.DB.MySQL.Model(&tables.Roles{}).Select("IsCustom").Where("id=?", rsr.Id).Scan(&isCustom)
	if roleId != 2 && roleId == rsr.Id {
		return errors.NewErrInfo(10004, fmt.Errorf("只能由上级管理员进行编辑"))
	}
	if !isCustom && roleId != 2 {
		return errors.NewErrInfo(10003, fmt.Errorf("内置角色只能由系统的超级管理员编辑"))
	}
	belongId := 0
	var roleObj = new(tables.Roles)
	// 查询该角色是否存在
	r, err := roleObj.GetRolesByWhere(map[string]interface{}{"role_name": rsr.RoleName, "belong_to_id": belongId}, fmt.Sprintf("id != %d", rsr.Id))
	if err != nil || (len(r) != 0 && r[0].ID != 0) {
		return errors.NewErrInfo(10002, fmt.Errorf("该角色名已经存在~"))
	}
	bytePowers, _ := json.Marshal(rsr.Powers)
	var updates map[string]interface{}
	updates = make(map[string]interface{}, 0)
	updates["describe"] = rsr.Describe
	updates["role_name"] = rsr.RoleName
	updates["powers"] = string(bytePowers)

	if err := roleObj.UpdateRolesById(updates, int(rsr.Id)); err != nil {
		return errors.NewErrInfo(10003, fmt.Errorf("更新失败，请重新尝试"))
	}
	return nil
}

func (rs *RolesService) DeleteRolesById(ctx *gin.Context, ri model.RolesId) *errors.ErrRes {
	var roleObj = new(tables.Roles)
	// 查询该角色是否被使用
	users, err := new(tables.User).GetUsersByWhere(map[string]interface{}{"role_id": ri.Id}, "*")
	if err != nil {
		return errors.NewErrInfo(10001, fmt.Errorf("角色删除失败，请重新尝试"))
	}
	if len(users) != 0 && users[0].ID != 0 {
		return errors.NewErrInfo(10002, fmt.Errorf("该角色已绑定账号，不允许删除"))
	}

	if _, err := roleObj.DeleteRolesById(int(ri.Id)); err != nil {
		return errors.NewErrInfo(10003, fmt.Errorf("角色删除失败，请重新尝试"))
	}
	return nil
}

// 根据角色
func (r *RolesService) GetUserPermission(ctx *gin.Context) ([]string, *errors.ErrRes) {
	var roleUri []string
	// 1. 获取该用户的id
	uid, exists := ctx.Get("uid")
	if !exists {
		return roleUri, errors.NewErrInfo(10001, fmt.Errorf("您无权操作"))
	}
	us, _ := tables.GetAgentInfoByUid(uid.(uint))
	roleId := us.RoleId

	// 2. 根据roleId获取权限信息
	var whereStr = fmt.Sprintf("id in (1, %d)", roleId)
	rs, err := new(tables.Roles).GetRolesDetailByWhere(whereStr)
	if err != nil {
		return roleUri, errors.NewErrInfo(10002, fmt.Errorf("您查询的该用户不存在"))
	}
	for i := 0; i < len(rs); i++ {
		for _, v := range rs[i].Member {
			if us.Type == tables.UserTypeSadmin {
				if v.Other == "/dataOverview" || v.Other == "/trainingConfiguration" {
					continue
				}
			}
			roleUri = append(roleUri, v.ConfValue)
			if len(v.Other) != 0 {
				roleUri = append(roleUri, v.Other)
			}
		}
	}
	return roleUri, nil
}

// 获取该用户的页面权限
func (r *RolesService) GetPagePermission(ctx *gin.Context, ri model.RolesId) ([]model.RoleUriLable, *errors.ErrRes) {
	var roleUriLables []model.RoleUriLable
	// 1. 获取该用户的id
	roleId := ri.Id
	if roleId == 0 {
		uid, exists := ctx.Get("uid")
		if !exists {
			return roleUriLables, errors.NewErrInfo(10001, fmt.Errorf("您无权操作"))
		}
		us, _ := tables.GetAgentInfoByUid(uid.(uint))
		roleId = us.RoleId
	}

	// 2. 根据roleId获取权限信息
	var whereStr = fmt.Sprintf("id = %d", roleId)
	rs, err := new(tables.Roles).GetRolesDetailNoPubByWhere(whereStr)
	if err != nil {
		return roleUriLables, errors.NewErrInfo(10002, fmt.Errorf("您查询的该用户不存在"))
	}

	// 3. 组装数据
	for _, v := range rs.Member {
		var flag = true
		var rul model.RoleUriLable
		rul.Id = v.ID
		rul.Label = v.Remarks
		rul.Uri = v.ConfValue
		if v.Remarks == "其他" {
			continue
		}
		for i := 0; i < len(roleUriLables); i++ {
			if roleUriLables[i].Id == v.Type {
				flag = false
				roleUriLables[i].Value = append(roleUriLables[i].Value, &rul)
				break
			}
		}
		if flag {
			var rl model.RoleUriLable
			rl.Id = v.Type
			rl.Label = v.ExtendInfo
			rl.Value = append(rl.Value, &rul)
			roleUriLables = append(roleUriLables, rl)
		}
	}

	return roleUriLables, nil
}

// 角色 + 学校匹配校验
func (r *RolesService) RolesCheck(id uint, roleId uint) (bool, uint) {
	var whereMap map[string]interface{}
	whereMap = make(map[string]interface{}, 0)
	whereMap["id"] = id
	cons, _ := new(tables.Constitute).GetInfoByWhere(whereMap)
	whereStr := fmt.Sprintf("id = '%d'", roleId)
	roles, _ := new(tables.Roles).GetRolesByWhere(map[string]interface{}{}, whereStr)
	if len(roles) == 0 {
		return false, 0
	}
	if cons.ID == 0 || roles[0].ID == 0 {
		return false, 0
	}
	level := roles[0].Level
	if level == tables.RolesLevel1 {
		return true, tables.RolesLevel1
	}
	if cons.Type == tables.SchoolType && level == tables.RolesLevel2 {
		return true, tables.RolesLevel2
	}
	if cons.Type == tables.AcademyType && level == tables.RolesLevel3 {
		return true, tables.RolesLevel3
	}
	if cons.Type == tables.ProfessionType && level == tables.RolesLevel4 {
		return true, tables.RolesLevel4
	}
	return false, 0
}

// 根据roleid+uri判断用户是否拥有该权限
func (r *RolesService) GetRolesByRUI(roleId uint, uri, method string) bool {
	if roleId == 0 || len(uri) == 0 {
		return false
	}
	rs, err := new(tables.Roles).GetRolesDetailByWhere(fmt.Sprintf("id in (1,%d)", roleId))
	if err != nil {
		return false
	}
	for i := 0; i < len(rs); i++ {
		for _, v := range rs[i].Member {
			s := strings.Split(v.ConfValue, "@@")
			methodIsAllow := true
			if len(s) > 1 {
				methodIsAllow = method == s[1]
			}
			if uri == s[0] && methodIsAllow {
				return true
			}
		}
	}
	return false
}
